package com.metaweb.antTasks;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

public class CompilePackagesTask extends Task {
	public class Package {
		String _shortName;
		
		public void setShortname(String shortName) {
			_shortName = shortName;
		}
	}
	
	private List<Package> _packages = new ArrayList<Package>();
	private File		  _compilationsDir;
	private File		  _packagesDir;
	private String		  _name;
	
	public Package createPackage() {
		Package pkg = new Package();
		_packages.add(pkg);
		
		return pkg;
	}
	
	public void setName(String name) {
		_name = name;
	}
	
	public void setCompilations(File dir) {
		_compilationsDir = dir;
	}
	
	public void setPackages(File dir) {
		_packagesDir = dir;
	}
	
	@Override
	public void execute() throws BuildException {
		if (_compilationsDir == null) {
			throw new BuildException("No compilations dir specified.");
		}
		if (_packagesDir == null) {
			throw new BuildException("No packages dir specified.");
		}
		if (_name == null) {
			throw new BuildException("No name specified.");
		}
	
		compileJavascript();
		compileCSS();
    }
	
	private void compileJavascript() {
        try {
        	File compiledFile = new File(_compilationsDir, _name + ".js");
            OutputStream os = new FileOutputStream(compiledFile);
            os.write(new byte[] { (byte)0xEF, (byte)0xBB, (byte)0xBF });
            os.flush();
            
    		Writer writer = new OutputStreamWriter(os, Charset.forName("UTF-8"));
    		try {
    			writer.write("(function() {\n");
    			writer.write("  var mw = window.MetawebSuite;\n");
				for (Package pkg : _packages) {
					if (pkg._shortName != null) {
						writer.write("  mw.system.flagPackageAsCompiled(\"metaweb-suite-" + pkg._shortName + "\");\n");
					}
				}
				writer.write("})();\n");
				writer.flush();
				
				for (Package pkg : _packages) {
					if (pkg._shortName != null) {
						File pkgRootDir = new File(_packagesDir, pkg._shortName);
						File pkgMainFile = new File(pkgRootDir, pkg._shortName + "-package.js");
						
						appendJavascriptFile(os, writer, pkgMainFile);

		                File pkgBundleDir = new File(pkgRootDir, "bundle");
		                File pkgBundleFile = new File(pkgBundleDir, pkg._shortName + "-bundle.js");
		                
		                appendJavascriptFile(os, writer, pkgBundleFile);
					}
				}
    		} finally {
    			writer.close();
                os.close();
    		}
        } catch (IOException e) {
            throw new BuildException(e);
        }
        
        try {
        	File debugFile = new File(_compilationsDir, _name + "-debug.js");
            OutputStream os = new FileOutputStream(debugFile);
            os.write(new byte[] { (byte)0xEF, (byte)0xBB, (byte)0xBF });
            os.flush();
            
    		Writer writer = new OutputStreamWriter(os, Charset.forName("UTF-8"));
    		try {
    			writer.write("(function() {\n");
    			writer.write("  var mw = window.MetawebSuite;\n");
				for (Package pkg : _packages) {
					if (pkg._shortName != null) {
						writer.write("  mw.system.loadNativePackage(\"" + pkg._shortName + "\");\n");
					}
				}
				writer.write("})();\n");
				writer.flush();
    		} finally {
    			writer.close();
                os.close();
    		}
        } catch (IOException e) {
            throw new BuildException(e);
        }
	}
	
	static private void appendJavascriptFile(OutputStream os, Writer writer, File file) throws IOException {
        writer.write("\n\n/* " + file.getName() + " */\n");
        writer.flush();
        
        Utilities.appendUtf8File(os, file);
	}

	private void compileCSS() {
        try {
        	File compiledFile = new File(_compilationsDir, _name + ".css");
    		Writer writer = new FileWriter(compiledFile);
    		try {
				for (Package pkg : _packages) {
					if (pkg._shortName != null) {
						File pkgRootDir = new File(_packagesDir, pkg._shortName);
		                File pkgBundleDir = new File(pkgRootDir, "bundle");
		                File pkgBundleFile = new File(pkgBundleDir, pkg._shortName + "-bundle.css");
		                if (pkgBundleFile.exists()) {
		                	Utilities.appendCSSFile(writer, pkgBundleFile, compiledFile);
		                }
					}
				}
    		} finally {
    			writer.close();
    		}
        } catch (IOException e) {
            throw new BuildException(e);
        }
	}
}
